﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

public class StateMachineEditorData<S, T> where S : StateDataBase, new() where T : StateTransitionDataBase, new()
{
    public List<StateGUIData<S>> stateDataList = new List<StateGUIData<S>>();
    public List<TransitionGUIData<T>> transitionDataList = new List<TransitionGUIData<T>>();
    public List<TransitionGUIData<T>[]> transitionDataGroupList = new List<TransitionGUIData<T>[]>();

    //private StateMachineData<S, T> data;
    private SM_EditorController<S, T> editorController;

    public StateMachineEditorData(StateMachineData<S, T> data, SM_EditorController<S, T> editorController)
    {
        if (data == null)
            return;
        //this.data = data;
        this.editorController = editorController;

        foreach (var item in data.stateDataList)
        {
            AddStateEvent(item);
        }
        foreach (var item in data.transitionDataList)
        {
            AddTransitionEvent(item);
        }

        data.AddStateEvent = AddStateEvent;
        data.DeleteStateEvent = DeleteStateEvent;
        data.AddTransitionEvent = AddTransitionEvent;
        data.DeleteTransitionEvent = DeleteTransitionEvent;
    }

  private  void AddTransitionToGroup(TransitionGUIData<T> t)
    {
        TransitionGUIData<T>[] tArr = null;
        foreach (var item in transitionDataGroupList)
        {
            bool isEnd = false;
            if (item != null)
            {
                for (int i = 0; i < item.Length; i++)
                {
                    TransitionGUIData<T> arr = item[i];
                    if (arr == null)
                        continue;

                    if (arr.transitions[0].fromStateID == t.transitions[0].toStateID && arr.transitions[0].toStateID == t.transitions[0].fromStateID)
                    {
                        isEnd = true;
                        if (i == 0)
                        {
                            item[1] = t;
                        }
                        else
                        {
                            item[0] = t;
                        }
                        tArr = item;
                        break;
                    }
                }
            }

            if (isEnd) break;
        }

        if(tArr == null)
        {
            tArr = new TransitionGUIData<T>[2];
            tArr[0] = t;
            transitionDataGroupList.Add(tArr);
        }
    }
    private void DeleteTransitionToGroup(TransitionGUIData<T> t)
    {
        TransitionGUIData<T>[] tArr = null;
        foreach (var item in transitionDataGroupList)
        {
            bool isEnd = false;
            if (item != null)
            {
                for (int i = 0; i < item.Length; i++)
                {
                 

                    if (item[i] == t)
                    {
                        isEnd = true;
                        item[i] =null;
                        if(item[0] ==null && item[1] == null)
                        {
                            tArr = item;
                        }
                        break;
                    }
                }
            }

            if (isEnd) break;
        }

        if (tArr != null)
        {
           
            transitionDataGroupList.Remove(tArr);
        }
    }

    private void DeleteTransitionEvent(T t)
    {
        TransitionGUIData<T> GUIData = GetTransitionData(t);
        if (GUIData != null)
        {
            //Debug.Log("DeleteTransition :" + t.transitionID);
            if (editorController.OnTransitionDelete != null)
                editorController.OnTransitionDelete(GUIData, t);

            if (GUIData.transitions.Contains(t))
                GUIData.transitions.Remove(t);
            if (GUIData.transitions.Count == 0)
            {
                Debug.Log("DeleteTransitionGUI :" + t.transitionID);
                transitionDataList.Remove(GUIData);
                DeleteTransitionToGroup(GUIData);
            }

        }
    }

    private void AddTransitionEvent(T t)
    {
        TransitionGUIData<T> GUIData =GetTransitionData(t);
        if (GUIData == null)
        {
            GUIData = new TransitionGUIData<T>();
            GUIData.transitions.Add(t);
            transitionDataList.Add(GUIData);
            AddTransitionToGroup(GUIData);
        }
        else
        {
            GUIData.transitions.Add(t);
        }
        if (editorController.OnTransitionAdd != null)
            editorController.OnTransitionAdd(GUIData, t);
    }
    private void DeleteStateEvent(S t)
    {
        StateGUIData<S> stateGUI = GetStateGUIData(t.id);

        if (stateGUI != null)
        {
            stateDataList.Remove(stateGUI);

            if (editorController.OnStateDelete != null)
                editorController.OnStateDelete(stateGUI);
        }
    }
    private void AddStateEvent(S t)
    {
        StateGUIData<S> stateGUI = new StateGUIData<S>();
        stateGUI.stateData = t;
        stateDataList.Add(stateGUI);

        if (editorController.OnStateAdd != null)
            editorController.OnStateAdd(stateGUI);
    }
    private TransitionGUIData<T> GetTransitionData(T t)
    {
        TransitionGUIData<T> GUIData=null;
        foreach (var item in transitionDataList)
        {
            if (item.transitions.Count > 0)
            {
                T temp = item.transitions[0];
                if (temp.fromStateID == t.fromStateID && temp.toStateID == t.toStateID)
                {
                    GUIData = item;
                    break;
                }
            }
        }

        return GUIData;
    }



    public StateGUIData<S> GetStateGUIData(int id)
    {
        foreach (var item in stateDataList)
        {
            if (item.stateData.id == id)
                return item;
        }

        return null;
    }

    public Rect GetStateMachineGUIMaxRange()
    {
        Rect stateMachineMaxRange = Rect.zero;
        foreach (var ms  in stateDataList)
        {
            Rect range = ms.GUIRect;
            stateMachineMaxRange.xMin = stateMachineMaxRange.xMin > range.xMin ? range.xMin : stateMachineMaxRange.xMin;
            stateMachineMaxRange.xMax = stateMachineMaxRange.xMax < range.xMax ? range.xMax : stateMachineMaxRange.xMax;
            stateMachineMaxRange.yMin = stateMachineMaxRange.yMin > range.yMin ? range.yMin : stateMachineMaxRange.yMin;
            stateMachineMaxRange.yMax = stateMachineMaxRange.yMax < range.yMax ? range.yMax : stateMachineMaxRange.yMax;
        }

        return stateMachineMaxRange;
    }

    public void DrawGUI()
    {
        foreach (var item in transitionDataGroupList)
        {
            for (int i = 0; i < item.Length; i++)
            {
                TransitionGUIData<T> tran = item[i];
                if (tran != null)
                {
                    DrawTransitionGUIUtils<S, T>.DrawLine(tran, i);
                }
            }
        }
        for (int i = 0; i < stateDataList.Count; i++)
        {
            stateDataList[i].DrawGUI();
        }
    }

     
}

